/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

package desarrollosoft.ghce.vista.implementaciones;

import desarrollosoft.ghce.entidades.Especialidad;
import desarrollosoft.ghce.entidades.Profesional;
import desarrollosoft.ghce.entidades.Sexo;
import desarrollosoft.ghce.entidades.TipoDocumento;
import desarrollosoft.ghce.servicio.interfaces.IParserExcepciones;
import desarrollosoft.ghce.servicio.interfaces.IServicioProfesionales;
import desarrollosoft.ghce.soporte.SecurityUtil;
import desarrollosoft.ghce.vista.interfaces.Avisable;
import desarrollosoft.ghce.vista.interfaces.Estado;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.zkoss.zk.ui.Executions;
import org.zkoss.zk.ui.event.Event;
import org.zkoss.zk.ui.event.EventListener;
import org.zkoss.zk.ui.select.SelectorComposer;
import org.zkoss.zk.ui.select.annotation.Listen;
import org.zkoss.zk.ui.select.annotation.VariableResolver;
import org.zkoss.zk.ui.select.annotation.Wire;
import org.zkoss.zk.ui.select.annotation.WireVariable;
import org.zkoss.zul.Button;
import org.zkoss.zul.Combobox;
import org.zkoss.zul.ListModelList;
import org.zkoss.zul.Listbox;
import org.zkoss.zul.Listitem;
import org.zkoss.zul.ListitemRenderer;
import org.zkoss.zul.Messagebox;
import org.zkoss.zul.Textbox;
import org.zkoss.zul.Window;

/**
 *
 * @author ariel
 */
@VariableResolver(org.zkoss.zkplus.spring.DelegatingVariableResolver.class)
public class ControladoraAdministracionProfesionales extends SelectorComposer<Window> implements Avisable {
    
    @WireVariable("servicioProfesionales")
    private IServicioProfesionales servicioProfesionales;
    
    @WireVariable("parserExcepcionesProfesional")
    private IParserExcepciones parserExcepciones;
    
    private Estado estado;
    
    List<String> listaDatosBuscables;
    
    List<TipoDocumento> listaTiposDocumento;
    
    List<String> listaRoles;
    
    List<Sexo> listaSexos;
    
    List<Especialidad> listaTemporal;
    
    @Wire
    private Textbox textboxDato;
    
    @Wire
    private Combobox comboboxTipoDato;
    
    @Wire
    private Listbox listboxProfesionales;
    
    @Wire
    private Textbox textboxApellidos;
            
    @Wire
    private Textbox textboxNombres;
    
    @Wire
    private Combobox comboboxTipoDocumento;
            
    @Wire
    private Textbox textboxNumeroDocumento;
    
    @Wire
    private Textbox textboxNombreUsuario;
            
    @Wire
    private Combobox comboboxRol;
    
    @Wire
    private Textbox textboxTelefono;
    
    @Wire
    private Textbox textboxMail;
    
    @Wire
    private Combobox comboboxSexo;
    
    @Wire
    private Listbox listboxEspecialidades;
    
    @Wire
    private Button botonModificar;
    
    @Wire
    private Button botonEliminar;
    
    @Wire
    private Button botonReactivar;
    
    @Wire
    private Button botonResetear;
    
    @Wire
    private Button botonAgregarEspecialidad;
            
    @Wire
    private Button botonEliminarEspecialidad;
    
    @Wire
    private Button botonCancelar;
            
    @Wire
    private Button botonGuardar;

    @Override
    public void doAfterCompose(Window comp) throws Exception {
        hacerAntesDeDibujar();
        super.doAfterCompose(comp); // wire variables and event listners
        hacerDespuesDeDibujar();
    }
    
    private void hacerAntesDeDibujar() {
        // nada?
    }
    
    private void hacerDespuesDeDibujar() {
        listaDatosBuscables = servicioProfesionales.obtenerDatosBuscables();
        comboboxTipoDato.setModel(new ListModelList<>(listaDatosBuscables));
        
        listaTiposDocumento = servicioProfesionales.obtenerTiposDocumento();
        comboboxTipoDocumento.setModel(new ListModelList<>(listaTiposDocumento));
        
        listaRoles = servicioProfesionales.obtenerTodosRoles();
        comboboxRol.setModel(new ListModelList<>(listaRoles));
        
        listaSexos = servicioProfesionales.obtenerTodosSexo();
        comboboxSexo.setModel(new ListModelList<>(listaSexos));
        
        // setear render a listbox por el tema del rol
        ListitemRenderer rendererProfesionales = new RendererProfesionales();
        listboxProfesionales.setItemRenderer(rendererProfesionales);
        
        List<Profesional> listaProfesionales = servicioProfesionales.buscarTodosProfesionales();
        listboxProfesionales.setModel(new ListModelList<>(listaProfesionales));
        
        // setear estado de los botones
        setearEstado(Estado.CONSULTANDO);
    }
    
    @Listen("onSelect = #listboxProfesionales")
    public void eligieronProfesional() {
        Profesional profesionalElegido = listboxProfesionales.getSelectedItem().getValue();
        setearEstado(Estado.CONSULTANDO);
        setearCampos(profesionalElegido);
    }
    
    @Listen("onClick = #botonBuscar")
    public void clickBotonBuscar() {
        setearEstado(Estado.CONSULTANDO);
        
        String dato = textboxDato.getValue();
        int indiceTipoDato = comboboxTipoDato.getSelectedIndex();
        String tipoDato;
        if (indiceTipoDato < 0) {
            tipoDato = "Apellido";
        } else {
            tipoDato = listaDatosBuscables.get(indiceTipoDato);
        }
        
        List<Profesional> listaProfesionales = servicioProfesionales.buscarProfesionales(dato, tipoDato);
        listboxProfesionales.setModel(new ListModelList<>(listaProfesionales));
    }
    
    @Listen("onClick = #botonCrear")
    public void clickBotonCrear() {
        setearEstado(Estado.CREANDO);
        listaTemporal = new ArrayList<>(); // armo una nueva lista temporal
    }
    
    @Listen("onClick = #botonModificar")
    public void clickBotonModificar() {
        Listitem listitem = listboxProfesionales.getSelectedItem();
        if (listitem != null) {
            if (listitem.getValue() != null) {
                setearEstado(Estado.MODIFICANDO);
            }
        }
    }
    
    @Listen("onClick = #botonEliminar")
    public void clickBotonEliminar() {
        Listitem listitem = listboxProfesionales.getSelectedItem();
        if (listitem != null) {
            Profesional p = listitem.getValue();
            if (p != null && p.getBajaLogicaProfesional() == null) {
                try {
                    if (intentaModificarUsuarioActual(p)) {
                        Messagebox.show("No puede darse de baja a si mismo");
                        return;
                    }
                } catch (Exception ex) {
                    return;
                }
                /* tengo el elemento seleccionado */
                Map<String, Object> argumentos = new HashMap<>();
                argumentos.put("avisable", this);
                argumentos.put("profesional", p);
                Window ventana = (Window) Executions.createComponents("VentanaBajaLogicaProfesional.zul", null, argumentos);
                ventana.doModal();
            }
        }
    }
    
    @Listen("onClick = #botonReactivar")
    public void clickBotonReactivar() {
        Listitem listitem = listboxProfesionales.getSelectedItem();
        if (listitem != null) {
            final Profesional profesional; // GUADA QUE QUEDO FINAL para editarlo
            if ((profesional = listitem.getValue()) != null) {
                if (profesional.getBajaLogicaProfesional() != null) { // no permitir iniciar sesion a dados de baja
                    // preguntar si esta seguro y llamar a servicio
                    Messagebox.show("¿Confirma que desea Reactivar al usuario seleccionado?", "Confirme por favor",
                            Messagebox.YES | Messagebox.NO, Messagebox.QUESTION,
                            new EventListener() {
                                @Override
                                public void onEvent(Event evt) throws InterruptedException {
                                    if (evt.getName().equals("onYes")) { // si confirma
                                        try {
                                            servicioProfesionales.reactivarProfesional(profesional);
                                        } catch (Exception e) {
                                            // habria q atravesar x el parser !!!!
                                            Messagebox.show(e.toString());
                                            return;
                                        }
                                        clickBotonBuscar(); // hago como que buscaron para actualizar la tabla
                                    }
                                }
                            }
                    );
                }
            }
        }
    }

    @Listen("onClick = #botonResetear")
    public void clickBotonResetear() {
        Listitem listitem = listboxProfesionales.getSelectedItem();
        if (listitem != null) {
            final Profesional profesional;
            if ((profesional = listitem.getValue()) != null) {
                try {
                    if (intentaModificarUsuarioActual(profesional)) {
                        Messagebox.show("No puede resetear la contrasenia de usted mismo");
                        return;
                    }
                } catch (Exception e) {
                    // deberia pasar por el parser
                    Messagebox.show("Error al comprobar si era el usuario actual: " + e.toString());
                    return;
                }
                if (profesional.getBajaLogicaProfesional() != null) {
                    Messagebox.show("No puede resetear la contraseña de un Usuario dado de baja");
                    return;
                }
                Messagebox.show("¿Confirma que desea Resetear la contraseña al usuario seleccionado?", "Confirme por favor",
                        Messagebox.YES | Messagebox.NO, Messagebox.QUESTION,
                        new EventListener() {
                            @Override
                            public void onEvent(Event evt) throws InterruptedException {
                                if (evt.getName().equals("onYes")) { // si confirma
                                    try {
                                        servicioProfesionales.resetearContrasenia(profesional);
                                    } catch (Exception e) {
                                        // habria q atravesar x el parser !!!!
                                        Messagebox.show(e.toString());
                                        return;
                                    }
                                    Messagebox.show("Se reseteo correctamente la contraseña del usuario seleccionado");
                                    //clickBotonBuscar(); // hago como que buscaron para actualizar la tabla
                                }
                            }
                        }
                );
            }
        }
    }
    
    @Listen("onClick = #botonCambiarContrasenia")
    public void clickBotonCambiarContrasenia() {
        Listitem listitem = listboxProfesionales.getSelectedItem();
        if (listitem != null) {
            Profesional profesionalSeleccionado = listitem.getValue();
            if (profesionalSeleccionado != null) {
                String nombreUsuarioActual = SecurityUtil.getUserName();
                Profesional profesionalActual;
                try {
                    profesionalActual = servicioProfesionales.obtenerProfesional(nombreUsuarioActual);
                } catch (Exception ex) {
                    Messagebox.show("ERROR INESPERADO al obtener el Profesional actual");
                    return;
                }
                if (!profesionalActual.equals(profesionalSeleccionado)) {
                    Messagebox.show("Solo puede cambiar la contraseña de su propio Usuario");
                    return;
                }
                Map<String,Object> argumentos = new HashMap<>();
                argumentos.put("profesional", profesionalActual);
                Window ventana = (Window) Executions.createComponents("VentanaCambiarContrasenia.zul", null, argumentos);
                ventana.doModal();
            }
        }
    }
    
    @Listen("onClick = #botonGuardar")
    public void clickBotonGuardar() {
        if (estado.equals(Estado.CREANDO)) {
            try {
                Profesional profesional = obtenerProfesionalDeCampos();
                profesional.setContrasenia(profesional.getNombreUsuario()); // por defecto, contrasenia igual a nombre de usuario
                servicioProfesionales.crearProfesional(profesional);
                //setearEstado(Estado.CONSULTANDO);
                clickBotonBuscar();
            } catch (Exception ex) {
                Messagebox.show(parserExcepciones.parsear(ex.toString()));
            }
        } else if (estado.equals(Estado.MODIFICANDO)) {
            
            try {
                Profesional profesional = obtenerProfesionalDeCampos();
                Profesional profesionalElegido = listboxProfesionales.getSelectedItem().getValue();
                
                if (intentaModificarUsuarioActual(profesionalElegido)) {
                    Messagebox.show("No puede Modificar sus propios datos");
                    return;
                }
                
                profesional.setId(profesionalElegido.getId());
                profesional.setContrasenia(profesionalElegido.getContrasenia());
                servicioProfesionales.modificarProfesional(profesional);
                //setearEstado(Estado.CONSULTANDO);
                clickBotonBuscar();
            } catch (Exception ex) {
                Messagebox.show(parserExcepciones.parsear(ex.toString()));
            }
        }
    }
    
    @Listen("onClick = #botonCancelar")
    public void clickBotonCancelar() {
        listboxProfesionales.selectItem(null);
        setearEstado(Estado.CONSULTANDO);
        clickBotonBuscar();
    }
    
    @Listen("onClick = #botonAgregarEspecialidad")
    public void clickAgregarEspecialidad() {
        if (estado.equals(Estado.MODIFICANDO)) {
            Profesional p = listboxProfesionales.getSelectedItem().getValue();

            if (p.getEspecialidades() == null) {
                p.setEspecialidades(new ArrayList<Especialidad>());
            }

            listaTemporal = p.getEspecialidades();
        } else if (estado.equals(Estado.CREANDO)) {
            //listaTemporal = new ArrayList<>();
            // no hago nada
        }
        
        
        Map<String, Object> argumentos = new HashMap<>();
        argumentos.put("avisable", this);
        argumentos.put("listaEspecialidadesProfesional", listaTemporal);
        Window ventana = (Window) Executions.createComponents("VentanaBusquedaEspecialidad.zul", null, argumentos);
        ventana.doModal();
    }
    
    @Listen("onClick = #botonEliminarEspecialidad")
    public void clickEliminarEspecialidad() {
        Listitem li = listboxEspecialidades.getSelectedItem();
        if (li != null) {
            Especialidad e = li.getValue();
            listaTemporal.remove(e);
            listboxEspecialidades.setModel(new ListModelList<>(listaTemporal));
        }
    }
    
    /**
     * Devuelve true si se intenta modificar el usuario actual
     * @return 
     */
    private boolean intentaModificarUsuarioActual(Profesional profesionalModificar) throws Exception {
        String nombreUsuario = SecurityUtil.getUserName();
        Profesional profesionalActual = servicioProfesionales.buscarPorNombreUsuario(nombreUsuario);
        return profesionalActual.equals(profesionalModificar);
    }
    
    private Profesional obtenerProfesionalDeCampos() {
        Profesional p = new Profesional();
        
        p.setApellido( (textboxApellidos.getValue().isEmpty()) ? null : textboxApellidos.getValue() );
        p.setNombre( (textboxNombres.getValue().isEmpty()) ? null : textboxNombres.getValue() );
        p.setTipoDocumento( (comboboxTipoDocumento.getSelectedIndex() < 0) ? null : listaTiposDocumento.get(comboboxTipoDocumento.getSelectedIndex()) );
        p.setNumeroDocumento( (textboxNumeroDocumento.getValue().isEmpty() ) ? null : textboxNumeroDocumento.getValue());
        p.setNombreUsuario( (textboxNombreUsuario.getValue().isEmpty()) ? null : textboxNombreUsuario.getValue());
        p.setRol( (comboboxRol.getSelectedIndex() < 0) ? null : (Integer) comboboxRol.getSelectedIndex());
        p.setTelefono( (textboxTelefono.getValue().isEmpty()) ? null : textboxTelefono.getValue() );
        p.setMail( (textboxMail.getValue().isEmpty()) ? null : textboxMail.getValue());
        p.setSexo( (comboboxSexo.getSelectedIndex() < 0) ? null : listaSexos.get(comboboxSexo.getSelectedIndex()) );
        p.setEspecialidades(listaTemporal);
        return p;
    }
    
    private void setearEstado(Estado estado) {
        this.estado = estado;
        if (estado.equals(Estado.CONSULTANDO)) { // consultando
            habilitarBotonesGuardarCancelar(false);
            limpiarCampos();
            camposSoloLectura(true);
        } else if (estado.equals(Estado.CREANDO)) { // creando
            habilitarBotonesGuardarCancelar(true);
            limpiarCampos();
            camposSoloLectura(false);
        } else if (estado.equals(Estado.MODIFICANDO)) { // modificando
            habilitarBotonesGuardarCancelar(true);
            camposSoloLectura(false);
        }
    }
    
    private void habilitarBotonesGuardarCancelar(boolean valor) {
        botonModificar.setDisabled(valor);
        botonEliminar.setDisabled(valor);
        botonReactivar.setDisabled(valor);
        botonResetear.setDisabled(valor);
        
        botonGuardar.setDisabled(!valor);
        botonCancelar.setDisabled(!valor);
        botonAgregarEspecialidad.setDisabled(!valor);
        botonEliminarEspecialidad.setDisabled(!valor);
    }
    
    private void camposSoloLectura(boolean valor) {
        
        textboxApellidos.setReadonly(valor);
        textboxNombres.setReadonly(valor);
        
        comboboxTipoDocumento.setReadonly(valor);
        comboboxTipoDocumento.setButtonVisible(!valor);
        
        textboxNumeroDocumento.setReadonly(valor);
        textboxNombreUsuario.setReadonly(valor);
        
        comboboxRol.setReadonly(valor);
        comboboxRol.setButtonVisible(!valor);
        
        textboxTelefono.setReadonly(valor);
        textboxMail.setReadonly(valor);
        
        comboboxSexo.setReadonly(valor);
        comboboxSexo.setButtonVisible(!valor);
    }
    
    private void limpiarCampos() {
        textboxApellidos.setValue(null);
        textboxNombres.setValue(null);
        comboboxTipoDocumento.setSelectedIndex(-1);
        textboxNumeroDocumento.setValue(null);
        textboxNombreUsuario.setValue(null);
        comboboxRol.setSelectedIndex(-1);
        textboxTelefono.setValue(null);
        textboxMail.setValue(null);
        comboboxSexo.setSelectedIndex(-1);
        listboxEspecialidades.setModel(new ListModelList<Especialidad>());
        listaTemporal = null;
    }
    
    private void setearCampos(Profesional profesional) {
        textboxApellidos.setValue(profesional.getApellido());
        textboxNombres.setValue(profesional.getNombre());
        
        comboboxTipoDocumento.setSelectedIndex(listaTiposDocumento.indexOf(profesional.getTipoDocumento()));
        
        textboxNumeroDocumento.setValue(profesional.getNumeroDocumento());
        textboxNombreUsuario.setValue(profesional.getNombreUsuario());
        
        comboboxRol.setSelectedIndex(profesional.getRol());

        textboxTelefono.setValue(profesional.getTelefono());
        textboxMail.setValue(profesional.getMail());
        
        comboboxSexo.setSelectedIndex(listaSexos.indexOf(profesional.getSexo()));
        
        listaTemporal = profesional.getEspecialidades();
        listboxEspecialidades.setModel(new ListModelList<>(listaTemporal));
    }

    @Override
    public void seCerroVentanaHija(String nombre) {
        if ("especialidad".equals(nombre)) {
            if (estado.equals(Estado.MODIFICANDO)) {
                Profesional p = listboxProfesionales.getSelectedItem().getValue();
                listboxEspecialidades.setModel(new ListModelList<>(p.getEspecialidades()));
            } else if (estado.equals(Estado.CREANDO)) {
                listboxEspecialidades.setModel(new ListModelList<>(listaTemporal));
            }
        } else {
            clickBotonBuscar();
        }
    }
}
